home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
nhclb120.zoo
/
plus.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-11
|
13KB
|
619 lines
/* OS- and machine-dependent stuff for HP 110+ running MS-DOS */
#if defined(__TURBOC__)
#pragma inline
#include <stdio.h>
#include "config.h"
#if defined(PLUS)
#include "global.h"
#include "8250.h"
#include "asy.h"
#include "plus.h"
#include "iface.h"
struct asy asy[ASY_MAX];
unsigned nasy;
byte model;
void _Cdecl __int__ (int interruptnum);
void interrupt (* _Cdecl getvect(int interruptno)) ();
#define geninterrupt(i) __int__(i)
extern unsigned char intstk[];
extern unsigned int sssave, spsave;
/*
=================================================================
*/
int16 modemdev, serialdev;
struct plusasy plusasy[ASY_MAX];
/* ASY interrupt handlers */
byte modemconfig, serialconfig;
extern void interrupt plustxsvec();
extern void interrupt plusrxsvec();
extern void interrupt plustxmvec();
extern void interrupt plusrxmvec();
byte *com1_name="COM1"; /* file to open for serial */
byte *com3_name="COM3"; /* file to open for modem */
int com1handle; /* file handle saved here */
int com3handle; /* file handle saved here */
byte *ioctlon1="M1;"; /* IOCTL to turn on serial port */
byte *ioctloff1="M3;"; /* IOCTL to turn off serial port */
byte *ioctlon3="M4;"; /* IOCTL to turn on modem port */
byte *ioctloff3="M5;"; /* IOCTL to turn off modem port */
/* Initialize asynch port "dev" */
int
asy_init(dev,arg1,arg2,bufsize)
int16 dev;
char *arg1,*arg2;
unsigned bufsize;
{
register unsigned base;
register struct fifo *fp;
register struct asy *ap;
ap = &asy[dev];
ap->addr = htoi(arg1);
ap->vec = htoi(arg2);
/* Set up receiver FIFO */
fp = &ap->fifo;
if((fp->buf = malloc(bufsize)) == NULLCHAR){
printf("asy%d: No space for rx buffer\r\n");
fflush(stdout);
return;
}
fp->bufsize = bufsize;
fp->wp = fp->rp = fp->buf;
fp->cnt = 0;
base = ap->addr;
/* Purge the receive data buffer
* Set line control register: 8 bits, no parity
*
* Turn on receive interrupt enable, leave transmit
* interrupts turned off for now
*
* Set modem control register: assert DTR, RTS, turn on serial
* port
*
* Enable rx interrupt
*/
(void)init_com(dev,'N',1);
/*
* set calibration in delay
*/
/*
* turn off lousy beeper on ring interrupts.
*/
_AL=2;
__int__(0x59);
/* Set interrupt vector to SIO handler
* DON'T bump them by 8 as we use the actual
* interrupt numbers, not the number -8 as in
* the pc asy entry.
*
* If the computer is a portable only the serial interrupts are used
* If the computer is a P+ both serial and modem interrupts are used
*
* 110 110p serial 110p modem
* rx vector 0x4f 0x4f 0x4e
* tx vector 0x4a 0x4a 0x40
* base addr 0xa4 0x44 0xa4
*
*/
if(base==0x44 || model==1) {
plusasy[dev].oldrx=getvect(0x4f);
plusasy[dev].oldtx=getvect(0x4a);
if(model==1) {
asy[dev].addr=0xa4;
setvect(0x4a,plustxmvec);
setvect(0x4f,plusrxmvec);
modemdev=dev;
}
else {
setvect(0x4a,plustxsvec);
setvect(0x4f,plusrxsvec);
serialdev=dev;
}
}
else { /* address not 0x44 and not a portable, must be plus modem */
plusasy[dev].oldrx=getvect(0x4e);
plusasy[dev].oldtx=getvect(0x40);
setvect(0x40,plustxmvec);
setvect(0x4e,plusrxmvec);
modemdev=dev;
}
} /* asy_init */
int
asy_stop(iface)
struct interface *iface;
{
register unsigned base;
register struct asy *ap;
ap = &asy[iface->dev];
base = ap->addr;
/*
* hardware ints off
*/
outportb(base+INTRCONTROL,(unsigned char)0xf0);
/*
* turn off power to the serial port and
* Restore original interrupt vectors
*/
if(base==0x44 || model==1) {
serial_power(0);
setvect(0x4f,plusasy[iface->dev].oldrx);
setvect(0x4a,plusasy[iface->dev].oldtx);
}
else {
modem_power(0);
setvect(0x4e,plusasy[iface->dev].oldrx);
setvect(0x40,plusasy[iface->dev].oldtx);
}
return(0);
}
/* Asynchronous line I/O control */
asy_ioctl(interface,argc,argv)
struct interface *interface;
int argc;
char *argv[];
{
if(argc < 1){
printf("%d\r\n",asy[interface->dev].speed);
return 0;
}
return asy_speed(interface->dev,atoi(argv[0]));
}
/* Set asynch line speed */
int
asy_speed(dev,speed)
int16 dev;
int speed;
{
register unsigned base;
register int divisor;
char i_state;
if(speed == 0 || dev >= nasy)
return;
base = asy[dev].addr;
asy[dev].speed = speed;
/*
* Setup baud rate
*/
divisor=1333500L/speed - 1;
i_state = disable();
outportb((unsigned)(base+BAUDLO), (unsigned char)(divisor));
outportb((unsigned)(base+BAUDHI), (unsigned char)(divisor>>8));
restore(i_state);
}
/* Send a buffer to serial transmitter */
asy_output(dev,buf,cnt)
unsigned dev;
char *buf;
unsigned short cnt;
{
register struct dma *dp;
unsigned base;
char i_state;
if(cnt == 0)
return;
if(dev >= nasy)
return;
base = asy[dev].addr;
dp = &asy[dev].dma;
i_state = disable();
if(dp->flags){
restore(i_state);
return; /* Already busy */
}
dp->data = buf;
dp->cnt = cnt;
dp->flags = 1;
/* Enable transmitter buffer empty interrupt and simulate
* an interrupt; this will get things rolling.
*/
clrbit(base+INTRCONTROL,0x80);
setbit(base+INTRCONTROL,0x40);
asytxint(dev);
restore(i_state);
}
/* Receive characters from asynch line
* Returns count of characters read
*/
int16
asy_recv(dev,buf,cnt)
int16 dev;
char *buf;
unsigned cnt;
{
unsigned tot,n;
int kbread();
char i_state;
struct fifo *fp;
fp = &asy[dev].fifo;
tot = 0;
/* Read from serial I/O input buffer */
i_state = disable();
for(;;){
n = min(cnt,fp->cnt);
if(n == 0)
break;
n = min(n,&fp->buf[fp->bufsize] - fp->rp);
memcpy(buf,fp->rp,n);
fp->rp += n;
if(fp->rp >= &fp->buf[fp->bufsize])
fp->rp = fp->buf;
fp->cnt -= n;
buf += n;
tot += n;
cnt -= n;
}
restore(i_state);
return tot;
}
/* Process 110P receiver interrupts */
static
asyrxint(dev)
unsigned dev;
{
unsigned base;
register struct fifo *fp;
char c;
base = asy[dev].addr;
fp = &asy[dev].fifo;
c = inportb(base+RXDATA);
/* Process incoming data;
* If buffer is full, we have no choice but
* to drop the character
*/
if(fp->cnt != fp->bufsize){
*fp->wp++ = c;
if(fp->wp == &fp->buf[fp->bufsize])
/* Wrap around */
fp->wp = fp->buf;
fp->cnt++;
}
}
/* Handle 110P transmitter interrupts */
static
asytxint(dev)
unsigned dev;
{
register struct dma *dp;
register unsigned base;
base = asy[dev].addr;
dp = &asy[dev].dma;
if(!dp->flags){
/* "Shouldn't happen", but disable transmit
* interrupts anyway
*/
setbit(base+INTRCONTROL,0xc0);
return; /* Nothing to send */
}
while(inportb(base+STATUS) & 0x02){
outportb(base+TXDATA,*dp->data++);
if(--dp->cnt == 0){
dp->flags = 0;
/* Disable transmit interrupts */
setbit(base+INTRCONTROL,0xc0);
break;
}
/*
* turn em back on, we got more to do
*/
clrbit(base+INTRCONTROL,0x80);
setbit(base+INTRCONTROL,0x40);
}
}
int
stxrdy(dev)
int16 dev;
{
return(!asy[dev].dma.flags);
}
/* Set bit(s) in I/O port */
setbit(port,bits)
unsigned port;
char bits;
{
outportb(port,(char)inportb(port)|bits);
}
/* Clear bit(s) in I/O port */
clrbit(port,bits)
unsigned port;
char bits;
{
outportb(port,(char)(inportb(port) & ~bits));
}
int init_com(dev,wordlen,parity)
int dev, wordlen;
char parity;
{
int i, offset, sconfig;
i=peek(0xffff,0x0e) & 0xff;
if(i==0xb6) {
model=1; /* portable */
asy[dev].ad